#!/usr/bin/perl
use Getopt::Long;
use strict;

# TODO
# command line parameters solution with getopt
# package spec & body merge
# better file handling
# skip unixtodos for ISP

# list of default directories
my @dir_array;

# name and version of the project
my ($project, $proj_name, $uproj_name, $proj_ver);
my @p_params;
my ($oldversion, $dbversion);

# action - what to do ( create|clean|pack ) 
my $action;

# current work directory
my $cwd;

# scriptname
my $scriptname;

my $timestring;
my $creator;

my $new_sql_list;

$scriptname = $0;

# usage
if ( !$ARGV[0] ) {
    &usage();
}

$project    = $ARGV[0];
$cwd        = $ENV{PWD};
#$basename   = basename($0);

# project name, if its one word abbrevation 
@p_params   = split( /_/,$project); 
$proj_name  = shift(@p_params);
$proj_ver   = join('.',@p_params);
$uproj_name = uc($proj_name);
undef @p_params;

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);

$mon    += 1;
$year   += 1900;

$timestring = "$mday.$mon.$year";
$creator    = "Attila Bahik";


# action
if ( $ARGV[1] ) {
    $action = $ARGV[1];
}
else {
    $action = 'create';
}

# oldversion 
if ( $ARGV[2] ) {
    $oldversion = $ARGV[2];
}
else {
    undef $oldversion;
}

# directory structure
@dir_array  = (
    "tables",
    "views",
    "sequences",
    "types",
    "data",
    "packages",
    "triggers",
    "synonyms",
    "grants"
);

if ( $action eq 'create' ) {
    print "Initializing project: $proj_name version $proj_ver\n";
    &dirCreate();
    &addCompile();
    &addReadme();

}
elsif ( $action eq 'pack' ) {
    &dirDelete();
    &dirCheck();
    &addDBversion();
    &addInstallScript();
    &unix2dosFiles();
    # &createZip();
}

exit 0;


# SUBS

# create directories

sub dirCreate {
    map { system("mkdir -p $project/$_") } @dir_array;
    print "Directories created.\n";
    
    return 0;
}


# delete empty directories

sub dirDelete {
    map { system("rmdir $project/$_ 2>/dev/null") } @dir_array;
    print "Directories deleted.\n";
    
    return 0;
}


# windows style lineends
# TODO - for ISP skip this step

sub unix2dosFiles {
    system("unix2dos $project/* 2>/dev/null");
    map { system("unix2dos $project/$_/* 2>/dev/null") } @dir_array;
    print "unix2dos ready.\n";
    
    return 0;
}


# chec for all database modifications

sub dirCheck {
    my ( @result, $alter_cursor );

    # force
    $alter_cursor = "alter session set cursor_sharing=force;\n";

    foreach my $dir_type ( @dir_array ) {
        # cursor sharing before data load
        $new_sql_list .= $alter_cursor if ( "$dir_type" eq "data" );
        
        @result = <$project/$dir_type/*>;

        map { 
            # ignore CVS files
            if ( "$_" !~ m/CVS$/ ) {
                $new_sql_list .= "$_\n";
                $new_sql_list .= "show errors\n" if ( "$dir_type" eq "packages" );
            }
        
            # packages - show errors for packages
        } @result;
        

        # data - commit after data load
        $new_sql_list .= "commit;\n" if ( "$dir_type" eq "data" );

        # newlines
        $new_sql_list .= "\n";
    }
    
    # fix $new_sql_list, rmeove project tag and add @@ string to load scripts
    $new_sql_list =~ s/$project/\@\@./g;
    
    return 0;
}


# usage

sub usage {
    print <<USAGE;
Usage: $scriptname [name_of_the_project] [action] [oldversion]
    name_of_the_project - project name

    action: create      - create directory structure, create default files (default)
            clean       - cleanup
            pack        - makes cleanup, creates some install scripts and packs
    oldversion          - dot separated, 6.1.9
USAGE
    
    exit 0;
}


# adds the COMPILE.sql to the project directory

sub addCompile {
    open ( CMP, ">$project/COMPILE.sql") or die "cant open file $project/COMPILE.sql !\n";
    
    print CMP <<COMPILE;
REM --------------------------------------------------------------------------
REM This script will recompile all invalid database objects in 
REM the logged on users scheme.
REM %Version: Compile.dbsql BASE.1.3 29-MAY-2000 09:05                                                                                                                                       %
REM --------------------------------------------------------------------------

set heading off
set linesize 200
set pagesize 1000
set feedback off
PROMPT Compiling logged on Users Invalid Database Objects
spool temp_compile.sql
select 'alter function '|| object_name || ' compile;' from user_objects where
object_type='FUNCTION' and status='INVALID'
/
select 'alter procedure '|| object_name || ' compile;' from user_objects where
object_type='PROCEDURE' and status='INVALID'
/
select 'alter package '|| object_name || ' compile;' from user_objects where
object_type='PACKAGE' and status='INVALID'
/
select 'alter trigger '|| object_name || ' compile;' from user_objects where
object_type='TRIGGER' and status='INVALID'
/
select 'alter view '|| object_name || ' compile;' from user_objects where
object_type='VIEW' and status='INVALID'
/
select 'alter package '|| object_name || ' compile body;' from user_objects where
object_type='PACKAGE BODY' and status='INVALID'
/
--select 'alter index '|| index_name ||' rebuild compute statistics;' from user_indexes i
-- where i.funcidx_status = 'DISABLED'
--/

spool off
\@\@temp_compile.sql

spool compile.log
select object_name,object_type,status
from   all_objects
where  object_type in ('PROCEDURE','FUNCTION','PACKAGE','PACKAGE BODY','TRIGGER','VIEW')
and    status = 'INVALID'
and    owner = USER
order  by 1,2;
spool off

PROMPT End of Compile.
COMPILE

    close CMP;

    print "Compile\tCOMPILE.sql created.\n";
}


sub addReadme {
    open ( RME, ">$project/readme_$project.txt") or die "cant open file $project/readme_$project.txt !\n";

    print RME <<README;
-- ------------------------------------
-- Instalace aplikace $uproj_name $proj_ver (z $oldversion )
--
-- $timestring $creator
-- nasazeni: 
-- ------------------------------------

Ako uzivatel $uproj_name
    1. spustit $project.sql

Changes:
   -


README
    
    close(RME);

    print "Readme\treadme_$project.txt created.\n";
    return 0;
}



sub addReadmeKMP {
    open ( RME, ">$project/readme_$project.txt") or die "cant open file $project/readme_$project.txt !\n";

    print RME <<README;
-- ------------------------------------
-- Instalace aplikace $uproj_name $proj_ver (z $oldversion )
--
-- $timestring $creator
-- nasazeni: 
-- ------------------------------------

Ako uzivatel $uproj_name
    1. spustit $project.sql

Changes:
   -


README
    
    close(RME);

    print "Readme\treadme_$project.txt created.\n";
    
    return 0;
}


sub addInstallScript {
    open ( INSC, ">$project/$project.sql") or die "cant open file $project/$project.sql !\n";
    
    print INSC <<INSTSCR;
-- $uproj_name $proj_ver (z $oldversion )  $creator $timestring
--

spool $project.lst

set scan off
set define off
set feedback on
set serveroutput on

$new_sql_list

$dbversion

commit;

spool off

\@\@COMPILE
INSTSCR
    
    close INSC;

    print "Change the table create script order (cause of foreign keys)!\n";
    print "Change the table data scripts (foreign keys again)!\n";

    print "Install\t$project.sql created.\n";
    
    return 0;
}


# create the zipfile

sub createZip {
    
    system("zip -qr $project.zip $project/");
    my $returncode = $?;

    if ( "$returncode" ne "0" ) {
        print "Error occured at compressing files.\n";
        return $returncode;
    }
    
    print "Zipfile created.\n";
    
    return 0;
}


sub parseMainFile {
    return 0;
}


# db version updates

sub addDBversion {
			
	if ( $proj_name eq 'ppo' ) {
		$dbversion = 
"DELETE adt_parameters WHERE par_cd = 'VERSION';

INSERT INTO adt_paramters (par_cd, par_value, par_desc, valid_from, valid_to )
VALUES ('VERSION', '$proj_ver','PPO DB version', sysdate, null);";

	} 
	elsif ( 
	   $proj_name eq 'clk' |
	   $proj_name eq 'ctm' |
	   $proj_name eq 'pwb' | 
	   $proj_name eq 'bms' 
	) {
		$dbversion = 
"DELETE adt_parameters WHERE par_cd = 'DBVersion';

INSERT INTO adt_paramters (par_cd, par_value, par_desc, date_created, user_created )
VALUES ('DBVersion', '$proj_ver','DBversion', sysdate, null);";

	}
	elsif ( $proj_name eq 'kmp' ) {
		$dbversion = 
"DELETE adt_kmp_parameters WHERE par_cd = 'VERSION';

INSERT INTO adt_paramters (par_name, par_value, par_desc, valid_from, date_created, user_created, date_modified, user_modified )
VALUES ('VERSION', '$proj_ver','DB KMP version', sysdate, sysdate, null, sysdate, null);";

	}
	
	return 0;

}